#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
    acadauto.chm
    acad_aag.chm
    pyautocad.types
    ~~~~~~~~~~~~~~~

    3D Points and and other AutoCAD data types.
"""
import array
import operator
import math
import win32com.client
import pythoncom


def vtpnt(x, y ,z):
    """坐标点转化为浮点数"""
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x, y,z))

def vt2dpnt(x, y,z):
    """坐标点转化为浮点数"""
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x, y))

def vtobj(obj):
    """转化为对象数组"""
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_DISPATCH, obj)

def vtfloat(lst):
    """列表转化为浮点数"""
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, lst)

def vtint(lst):
    """列表转化为整数"""
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_I2, lst)

def vtvariant(lst):
    """列表转化为变体"""
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_VARIANT, lst)





class GPoint(win32com.client.VARIANT):
    """ 3D point with basic geometric operations and support for passing as a
        parameter for `AutoCAD` Automation functions

    Usage::

        >>> p1 = GPoint(10, 10)
        >>> p2 = GPoint(20, 20)
        >>> p1 + p2
        GPoint(30.00, 30.00, 0.00)

    Also it supports iterable as parameter::

        >>> GPoint([10, 20, 30])
        GPoint(10.00, 20.00, 30.00)
        >>> GPoint(range(3))
        GPoint(0.00, 1.00, 2.00)

    Supported math operations: `+`, `-`, `*`, `/`, `+=`, `-=`, `*=`, `/=`::

        >>> p = GPoint(10, 10)
        >>> p + p
        GPoint(20.00, 20.00, 0.00)
        >>> p + 10
        GPoint(20.00, 20.00, 10.00)
        >>> p * 2
        GPoint(20.00, 20.00, 0.00)
        >>> p -= 1
        >>> p
        GPoint(9.00, 9.00, -1.00)

    """
    def __init__(self, x_or_seq, y=0.0, z=0.0):
        if isinstance(x_or_seq, (array.array, list, tuple)) and len(x_or_seq) == 3:
            return super().__init__(pythoncom.VT_ARRAY | pythoncom.VT_R8, x_or_seq)
        else:
            return super().__init__(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x_or_seq, y, z))


  # -------------------属性操作-------------------------------    
    @property
    def x(self):
        """ x coordinate of 3D point"""
        return self._value[0]

    @x.setter
    def x(self, value):
        self._value = (value,self.value[1],self.value[2])

    @property
    def y(self):
        """ y coordinate of 3D point"""
        return self._value[1]

    @y.setter
    def y(self, value):
        self._value = (self.value[0],value,self.value[2])

    @property
    def z(self):
        """ z coordinate of 3D point"""
        return self._value[2]

    @z.setter
    def z(self, value):
        self._value = (self.value[0],self.value[1],value)

    def __getitem__(self, key):
        return self._value[key]


  # -------------------符号操作------------------------------- 
    def __add__(self, other):
        return self.__left_op(self, other, operator.add)

    def __sub__(self, other):
        return self.__left_op(self, other, operator.sub)

    def __mul__(self, other):
        return self.__left_op(self, other, operator.mul)

    def __div__(self, other):
        return self.__left_op(self, other, operator.truediv)

    __radd__ = __add__
    __rsub__ = __sub__
    __rmul__ = __mul__
    __rdiv__ = __div__
    __floordiv__ = __div__
    __rfloordiv__ = __div__
    __truediv__ = __div__
    _r_truediv__ = __div__

    def __neg__(self):
        return self.__left_op(self, -1, operator.mul)

    def __left_op(self, p1, p2, op):
        if isinstance(p2, (float, int)):
            return GPoint(op(p1[0], p2), op(p1[1], p2), op(p1[2], p2))
        return GPoint(op(p1[0], p2[0]), op(p1[1], p2[1]), op(p1[2], p2[2]))

    def __iadd__(self, p2):
        return self.__iop(p2, operator.add)

    def __isub__(self, p2):
        return self.__iop(p2, operator.sub)

    def __imul__(self, p2):
        return self.__iop(p2, operator.mul)

    def __idiv__(self, p2):
        return self.__iop(p2, operator.div)

    def __iop(self, p2, op):
        if isinstance(p2, (float, int)):
            self[0] = op(self[0], p2)
            self[1] = op(self[1], p2)
            self[2] = op(self[2], p2)
        else:
            self[0] = op(self[0], p2[0])
            self[1] = op(self[1], p2[1])
            self[2] = op(self[2], p2[2])
        return self

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        return 'GPoint(%.2f, %.2f, %.2f)' % tuple(self)

    def __eq__(self, other):
        if not isinstance(other, (array.array, list, tuple, GPoint)):
            return False
        return tuple(self) == tuple(other)

    # 其他操作
    def getPlanPoint(self):
        """获取二维点，仅x和y坐标"""
        return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8,(self.x, self.y))


class GRect():
    def __init__(self, pt1:GPoint, pt2:GPoint):
        self.pt1 = pt1
        self.pt2 = pt2


    @property
    def pt_1(self):
        return self.pt1

    @property
    def pt_2(self):
        return self.pt2


    @property
    def w(self):
        return abs(self.pt1.x - self.pt2.x)


    @property
    def h(self):
        return abs(self.pt1.y - self.pt2.y)


    def isPtnInRect(self,pt:GPoint):
        if abs(pt.x - self.pt1.x) + abs(pt.x - self.pt2.x) == self.w:
            return abs(pt.y - self.pt1.y) + abs(pt.y - self.pt2.y) == self.h
        return False


    def __str__(self):
        return f'GRect(({self.pt1.x:.3F},{self.pt1.y:.3F},{self.pt1.z:.3F}),({self.pt2.x:.3F},{self.pt2.y:.3F},{self.pt2.z:.3F}))'



if __name__ == '__main__':
    ptn1 = GPoint(5,33,2)
    ptn2 = GPoint(15.0,3.0,2.0)
    ptn3 = GPoint(10,22)
    a = GRect(ptn1, ptn2)
    print(a.isPtnInRect(ptn3))
    print(a,a.w,a.h)
    pass
    
